home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (C) 1997-1998, Tall Tree Software Co.
- *
- * This code is provided AS-IS, with no warranty expressed or implied.
- * in no way shall Tall Tree Software Co. be held liable for damages
- * brought about by the use of this software.
- */
-
- #include <windows.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
-
- #include <Rewriter Hook.h>
-
- struct GroupMarker {
- int line;
- char *group;
- };
-
- class SourceFile {
- const char *name;
- int numMarkers;
- int maxMarkers;
- GroupMarker *markers;
-
- public:
- void AddMarker( int line, const char *marker );
- const char *GetGroup( int line );
-
- private:
- static int numFiles;
- static int maxFiles;
- static SourceFile *sourceFiles;
-
- public:
- static SourceFile &Find( const char *file );
- static void Destroy();
- };
-
- int SourceFile::numFiles = 0;
- int SourceFile::maxFiles = 0;
- SourceFile *SourceFile::sourceFiles = 0;
-
- void SourceFile::AddMarker( int line, const char *marker )
- {
- if ( markers == 0 ) {
- maxMarkers = 100;
- markers = (GroupMarker *)malloc( maxMarkers * sizeof(GroupMarker) );
- }
- else if ( numMarkers == maxMarkers ) {
- maxMarkers *= 2;
- markers = (GroupMarker *)realloc( markers,
- maxMarkers * sizeof(GroupMarker) );
- }
- markers[numMarkers].line = line;
- markers[numMarkers].group = strdup( marker );
- ++numMarkers;
- }
-
- const char *SourceFile::GetGroup( int line )
- {
- int i = 0;
- for ( ; i < numMarkers && markers[i].line < line; ++i )
- ;
- if ( i > 0 )
- return( markers[i-1].group );
- else
- return( 0 );
- }
-
- SourceFile &SourceFile::Find( const char *file )
- {
- for ( int i = 0; i < numFiles; ++i ) {
- if ( sourceFiles[i].name == file )
- return( sourceFiles[i] );
- }
- if ( sourceFiles == 0 ) {
- maxFiles = 100;
- sourceFiles = (SourceFile *)malloc
- ( maxFiles * sizeof(SourceFile) );
- }
- else if ( numFiles == maxFiles ) {
- maxFiles *= 2;
- sourceFiles = (SourceFile *)realloc( sourceFiles,
- maxFiles * sizeof(SourceFile) );
- }
- sourceFiles[numFiles].name = file;
- sourceFiles[numFiles].numMarkers = 0;
- sourceFiles[numFiles].maxMarkers = 0;
- sourceFiles[numFiles].markers = 0;
- ++numFiles;
- return( sourceFiles[numFiles-1] );
- }
-
-
- void SourceFile::Destroy()
- {
- for ( int i = 0; i < numFiles; ++i ) {
- for ( int j = 0; j < sourceFiles[i].numMarkers; ++j )
- free( sourceFiles[i].markers[j].group );
- if ( sourceFiles[i].markers != 0 )
- free( sourceFiles[i].markers );
- }
- if ( sourceFiles != 0 ) {
- free( sourceFiles );
- // Let's be anal
- sourceFiles = 0;
- numFiles = 0;
- maxFiles = 0;
- }
- }
-
-
-
- char *sourceExtensions[] = { "c", "cc", "cpp", "cxx", "h", "hxx", "hpp", "inl",
- "cls", "bas", "frm", "ctl",
- "idl",
- 0 };
-
- extern "C" DLLEXPORT bool RewriteSource( const char *sourceFile,
- const char *tmpFile )
- {
- // See if this is a C, C++, IDL, or VB file...
- const char *ext = strrchr( sourceFile, '.' );
- assert( ext != 0 );
- if ( ext == 0 )
- return( false );
- ext += 1;
- char **ep = sourceExtensions;
- while ( *ep != 0 && 0 != stricmp( ext, *ep ) )
- ++ep;
- if ( *ep == 0 )
- return( false ); // not a source code file.
-
- // Here we'll scan the source file, looking for group
- // markers and remembering where we found them.
- FILE *f = fopen( sourceFile, "r" );
- assert( f != 0 );
- if ( f == 0 )
- return( false );
-
- SourceFile *source = &SourceFile::Find( sourceFile );
- char buf[1024];
-
- int line = 0;
- while ( fgets( buf, sizeof(buf), f ) ) {
- ++line;
-
- char *s = buf + strspn( buf, " \t" );
- if ( s[0] == '/' && s[1] == '/' )
- s += 2;
- else if ( s[0] == '/' && s[1] == '*' )
- s += 2;
- else if ( s[0] == '\'' )
- s += 1;
- else if ( 0 == _strnicmp( s, "rem ", 4 ) )
- s += 4;
- else if ( 0 == _strnicmp( s, "rem\t ", 4 ) )
- s += 4;
- else
- continue;
-
- // Okay, we got a comment line. See if it's a group directive...
- s += strspn( s, " \t" );
- if ( 0 != _strnicmp( s, "group", 5 ) )
- continue;
-
- s += 5;
- s += strspn( s, " \t" );
-
- if ( *s != '=' || *s == ':' )
- continue;
-
- s += 1;
- s += strspn( s, " \t" );
-
- char *end = buf+strlen(buf);
- while ( 0 != strchr( "\n \t", end[-1] ) )
- --end;
-
- if ( end[-1] == '/' && end[-2] == '*' ) {
- end -= 2;
- while ( 0 != strchr( "\n \t", end[-1] ) )
- --end;
- }
-
- *end = '\0';
-
- source->AddMarker( line, s );
- }
-
- fclose( f );
-
- // Now hunt for lines that look like:
- // // Group=<string>
- // or /* Group=<string> */
- // or ' Group=<string>
-
-
- // This allows you to rewrite a source file before it's sent
- // to the scanner. If you decide to rewrite the file, return
- // a boolean indicating whether you rewrote the file.
- return( false );
- }
-
-
- // The next bit of code should be retained verbatim. This is what
- // sets up the chain of hooks. You must implement either neither
- // or both of SetNextOnObjectFound and OnObjectFound.
-
- static HookReportFunction nextOnObjectFound;
-
- extern "C" DLLEXPORT
- void SetNextOnObjectFound( HookReportFunction onObjectFound )
- {
- nextOnObjectFound = onObjectFound;
- }
-
- Subtype rtfSubtypes[] = {
- { 0, "RTF Overview", PAPER_ID },
- { 0, 0, ABSTRACT_ID }
- };
-
- Subtype htmlSubtypes[] = {
- { 0, "HTML Overview", PAPER_ID },
- { 0, 0, ABSTRACT_ID }
- };
-
- Subtype glossarySubtypes[] = {
- { 0, "Overview", GLOSSARY_TERM_ID },
- { 0, 0, ABSTRACT_ID }
- };
-
- static bool IsOverviewGlossary( const char *p_sourceFile )
- {
- const char *s = strrchr( p_sourceFile, '\\' );
- if ( s == 0 )
- s = p_sourceFile;
- else
- s = s+1;
- return( 0 == stricmp( s, "overview.gls" ) );
- }
-
- static bool IsOverview( const char **p_extras )
- {
- while ( 0 != *p_extras ) {
- if ( 0 == stricmp( *p_extras, "overview" ) )
- return( *(p_extras[1]) != '\0' );
- p_extras += 2;
- }
- return( false );
- }
-
- extern "C" DLLEXPORT void OnObjectFound( const char *p_sourceFile,
- unsigned int p_commentStartLine,
- unsigned int p_declStartLine,
- const char *p_objectName,
- const Subtype &p_subtype,
- const char *p_superclass,
- const char *p_declaration,
- const char *p_comment,
- const char *p_body,
- char const **p_extras )
- {
- assert( nextOnObjectFound != 0 );
-
- const char *group = SourceFile::Find( p_sourceFile ).
- GetGroup( p_declStartLine );
-
- if ( IsOverviewGlossary(p_sourceFile ) ) {
- (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
- p_declStartLine, p_objectName,
- glossarySubtypes[0], p_superclass,
- p_declaration, p_comment,
- p_body, p_extras );
- }
- else if ( 0 == strcmp( p_subtype.fullname, "RTF Document" ) &&
- IsOverview( p_extras ) ) {
- (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
- p_declStartLine, p_objectName,
- rtfSubtypes[0], p_superclass,
- p_declaration, p_comment,
- p_body, p_extras );
- }
- else if ( 0 == strcmp( p_subtype.fullname, "HTML Document" ) &&
- IsOverview( p_extras ) ) {
- (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
- p_declStartLine, p_objectName,
- htmlSubtypes[0], p_superclass,
- p_declaration, p_comment,
- p_body, p_extras );
- }
- else if ( group == 0 ) {
- (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
- p_declStartLine, p_objectName, p_subtype,
- p_superclass, p_declaration, p_comment,
- p_body, p_extras );
- }
- else {
- int l = 0;
- for ( ; p_extras[l] != 0; l += 2 )
- ;
- char const **extras = new char const *[ l + 3 ];
- for ( l = 0; p_extras[l] != 0; l += 2 ) {
- extras[l] = p_extras[l];
- extras[l+1] = p_extras[l+1];
- }
- extras[l] = ATTR_DEFAULT_GROUP;
- extras[l+1] = group;
- extras[l+2] = 0;
- (*nextOnObjectFound)( p_sourceFile, p_commentStartLine,
- p_declStartLine, p_objectName, p_subtype,
- p_superclass, p_declaration, p_comment,
- p_body, extras );
- delete[l+3] extras;
- }
- }
-
- extern "C" DLLEXPORT void OnScanComplete()
- {
- SourceFile::Destroy();
- }
-
- extern "C" DLLEXPORT const Subtype *AugmentSubtypes
- ( const char *filetype, const Subtype *st )
- {
- if ( 0 == strcmp( filetype, "RTF Source" ) )
- return( rtfSubtypes );
- else if ( 0 == strcmp( filetype, "HTML Source" ) )
- return( htmlSubtypes );
- else if ( 0 == strcmp( filetype, "Glossary Source" ) )
- return( glossarySubtypes );
- else
- return( 0 );
- }
-
-